package com.fary.ibmmq;


import cn.hutool.core.util.StrUtil;
import com.fary.config.MQConfigProperties;
import com.fary.config.MQConfigProperties.Source;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.jms.*;

import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

/**
 * 接收消息
 */
@Component
@Scope(SCOPE_PROTOTYPE)
public class JmsMessageReceiver implements ExceptionListener {

    //节点标识
    private String nodeFlag;

    @Autowired
    private JmsConnectionFactoryProvider jmsConnectionFactoryProvider;

    @Autowired
    private MQConfigProperties mqConfigProperties;

    @Autowired
    private MQMessageListener mqMessageListener;

    // 上下文
    private JMSContext context;

    // 连接工厂
    private ConnectionFactory factory;


    /**
     * 初始化连接工厂和上下文
     */
    public void init() throws Exception {
        if (StrUtil.isBlank(nodeFlag)) {
            throw new RuntimeException("节点标识不能为空");
        }
        factory = jmsConnectionFactoryProvider.getConnectionFactory(nodeFlag, Constants.OP_TYPE_RECV);
        // 初始化上下文时，可选择是否开启事务
        // 不开启事务
        // context = factory.createContext(jmsConnectorProvider.getUser(),jmsConnectorProvider.getPassword(),Session.AUTO_ACKNOWLEDGE) ;
        // 开启事务
        context = factory.createContext(mqConfigProperties.getUser(), mqConfigProperties.getPassword(), Session.SESSION_TRANSACTED);
        // 设置为不自动开始
        context.setAutoStart(true);
        // 注意：若果在此处加上receive和start方法，则在onException方法中不需要再加上此方法，防止重置执行
        receive();
        start();
    }


    public void receive() throws Exception {
        Source source = jmsConnectionFactoryProvider.getSourceMap().get(nodeFlag);

        Destination destination = context.createQueue(source.getQueue());
        JMSConsumer consumer = context.createConsumer(destination);
        // 设置异常监听
        context.setExceptionListener(this);
        // 设置监听，当有消息到达时，监听器能收到消息
//        MQMessageListener messageListener = SpringUtil.getBean(MQMessageListener.class);
        mqMessageListener.setContext(context);
        consumer.setMessageListener(mqMessageListener);
//        consumer.setMessageListener(new MQMessageListener(context));
    }

    /**
     * 开始接收消息，执行receive方法后，不会立即接收消息，需要调用start方法才会接收消息
     */
    public void start() {
        context.start();
    }

    /**
     * 停止接收消息
     */
    public void stop() {
        context.stop();
    }


    /**
     * 释放资源
     */
    public void clean() throws Exception {
        if (factory != null) {
            factory = null;
        }
        if (context != null) {
            context.close();
            context = null;
        }
    }

    /**
     * 重连
     */
    private boolean reconnect() {
        try {
            clean();
            init();
            System.out.println("重连成功!");
            return true;
        } catch (Exception e) {
            System.out.println("重连失败!");
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 异常处理，重连后重新接收消息
     */
    @Override
    public void onException(JMSException arg0) {
        try {
            while (!reconnect()) {
                Thread.sleep(2000L);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public String getNodeFlag() {
        return nodeFlag;
    }

    public void setNodeFlag(String nodeFlag) {
        this.nodeFlag = nodeFlag;
    }


}
